package net.freestu.sola.web.parser.Parse;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.freestu.sola.web.util.FileManager;

public class Bridge {

	int EveryPages=300;         //每个个xml文件装多少的Page对象.
	
	private String name;        //文件夹名字
	private Set md5hash;        //判断MD5值。
	private File xmldatafolder; //放到xml文件去。在这个文件夹中存放二级域名的站点。
	private File crawlfolder;
	
	private String xmlpath;
	private String pagepath;
	
	private Map link2md5=new HashMap();
	/**
	 * 读取crawlfolder文件夹下面的网页,然后在xmldatafolder里面生成Xml文件
	 * @param name
	 * @param crawlfolder Crawl Folder
	 * @param xmldatafolder  XmlDataFolder文件夹
	 *            Xml Folder文件夹中，然后在里面生成www.cdut.edu.cn文件夹
	 */
	public Bridge(String name, File crawlfolder, File xmldatafolder) {

		this.name = name;
		this.crawlfolder = crawlfolder;    //Crawl Folder
		this.xmldatafolder = xmldatafolder;      //XmlData Folder
		md5hash = new HashSet();
		bxd();                           //在XmlData Folder下面创建www.cdut.edu.cn文件装xml文件。
		pagepath=crawlfolder.getAbsolutePath()+ File.separator + name;
		xmlpath = xmldatafolder.getAbsolutePath()+ File.separator + name;//xml文件放在的文件夹。XmlData Folder/lib.cdut.edu.cn
		// 这里文件路径是还没有确定的，所以需要动态进行分配。
	}
	
	public void exe(){
		
		
		System.out.println("crawlfolder:"+crawlfolder);
		
	  List htmlqueue=(ArrayList)FileManager.
         getPageFiles(pagepath);//P文件路径的结合。
	 
	  //每次从里面取出EveryPage个文件创建文件写入文件.
	  int time=(htmlqueue.size()/EveryPages)+1;
	  
	  
	  //1.创建1.xml文件
	  int t=time;
	  int j=1;
	  while(j<=t){
			
			FileManager.buildPageXml(xmlpath,String.valueOf(j)+".xml");
			j++;
	  }
	  
	  int i=1;
	  while(i<=time){
	    	
	    	List templist=getFrom(htmlqueue,EveryPages);//取出30个
	    	List tempOfpage=html2page(templist);// 这里如果一起读入内存的话，内存肯定不够用啊~~~~###修改~~~~
			write2xml(tempOfpage,new File(xmlpath,String.valueOf(i)+".xml"));
			i++;
	  }
	  writeLink2MD5();// 输出NewLink2MD5文件
	  System.out.println(name+":该进程执行完毕了!");
	}
	
	/**
	 * 将html的链表转化为pagelist(读入内存)
	 * @param htmllist
	 * @return 装有page的ArrayList
	 */
	public List html2page(List htmllist) {

		List pagelist = new ArrayList();
		Iterator it = htmllist.iterator();
		int i = 1;
		while (it.hasNext()) {

			String path = (String) it.next();
			File f = new File(path);
			// ---容错----
			if (!f.exists()) {
				return null;
			}
			// ----------
			// 这个地方的"成都理工大学"还没有情形动态分配???供测试用。可以从配置文件中获取.
			PageParser par = new PageParser(f, String.valueOf(i), "成都理工大学");
			Page p = par.getPage();
			String pagehash = p.getPagehash();

			//注意：这里的md5hash是公用的.
			if (!md5hash.contains(pagehash)) {// 判断在hash里面有无pagehash
				// 如果没有
				md5hash.add(pagehash);// 加入page
				pagelist.add(p);// 往写入到XML的Page对象。
				link2md5.put(p.getUrl(), pagehash);
				i++;
			} else {// 如果有则不再加入了。
				continue;// 继续循环
			}
		}
		return pagelist;
	}
	
	
	/**
	 * 将pagelist中的数据输出到xmlfile文件里面
	 * @param pagelist
	 * @param xmlfile
	 */
	public void write2xml(List pagelist, File xmlfile) {

		DataWriter de = new DataWriter(xmlfile);
		de.writePages(pagelist);
		pagelist.clear();
	}
	
	
	
	/**
	 * build xml dir 按二级域名进行创建
	 */
	public void bxd() {

		FileManager.buildDir(xmldatafolder.getAbsolutePath(), name);
	}
	
	/**
	 * 输出NewLink2MD5文件
	 */
	public void writeLink2MD5() {

		// 1.创建NewLink2MD5文件.
		// 2.往里面按link\\md5的格式输入。
		FileManager.buildFile(xmlpath, "NewLink2MD5");
		try {
			FileWriter fw = new FileWriter(xmlpath + File.separator
					+ "NewLink2MD5");
			BufferedWriter bw = new BufferedWriter(fw);
			Set entrySet = link2md5.entrySet();
			Iterator it = entrySet.iterator();

			while (it.hasNext()) {

				Map.Entry me = (Map.Entry) it.next();
				String key = (String) me.getKey();
				String value = (String) me.getValue();
				bw.write(key + "\\\\" + value);
				bw.newLine();
			}
			bw.close(); // 关闭流
			fw.close(); // 关闭流
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
	
	/**
	 * 从list中提取num个元素出来，然后删除原来的
	 * @param list
	 * @param num
	 * @return
	 */
	private List getFrom(List list,int num){
		
		List outlist=new ArrayList();
		int j = 0;
		while (j < num) {
			try {
				outlist.add(list.remove(0));
			} catch (IndexOutOfBoundsException e) {//不知道这样处理好不好
				break;
			}
			j++;
		}
		return outlist;
	}
	
	public static void main(String[] args){
		
		File f = new File(
				"D:\\工作室收藏\\编程工作室\\JAVA区\\Java程序调试区"
						+ "\\搜索引擎\\workspace\\Work_Place\\成都理工大学\\Crawl Folder\\www.cdut.edu.cn");
		new Bridge("www.cdut.edu.cn", f, new File("../")).exe();
	}
}